package com.android.example.app3;

import android.content.Context;
import android.os.Build;
import android.util.Log;

import androidx.annotation.NonNull;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

public class CustomExceptionHandler implements Thread.UncaughtExceptionHandler {

    private static final String TAG = "CustomExceptionHandler";
    private static final String LOG_FILE_NAME = "crash_log.txt";
    private static final String LOG_DIR_NAME = "MyAppLogs"; // 日志文件存放的目录名

    private final Context context;
    private final Thread.UncaughtExceptionHandler defaultUEH; // 保存系统默认的异常处理器

    public CustomExceptionHandler(Context context) {
        this.context = context.getApplicationContext(); // 使用 Application Context
        this.defaultUEH = Thread.getDefaultUncaughtExceptionHandler();
    }

    @Override
    public void uncaughtException(@NonNull Thread t, @NonNull Throwable e) {
        // 1. 获取错误信息
        String errorInfo = getErrorInfo(t, e);

        // 2. 将错误信息写入日志文件
        writeErrorLogToFile(errorInfo);

        // 3. （可选）可以在这里添加上报错误的逻辑，例如发送到服务器
        // sendErrorToServer(errorInfo);

        // 4. 调用系统默认的异常处理器来处理（通常会导致应用退出）
        // 注意：在某些情况下，你可能希望跳过默认处理，或者先做一些清理再退出
        defaultUEH.uncaughtException(t, e);
    }

    private String getErrorInfo(Thread t, Throwable e) {
        StringBuilder errorBuffer = new StringBuilder();
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.getDefault());
        String timestamp = dateFormat.format(new Date());

        errorBuffer.append("=====================================\n");
        errorBuffer.append("Crash Time: ").append(timestamp).append("\n");
        errorBuffer.append("Thread ID: ").append(t.getId()).append(", Name: ").append(t.getName()).append("\n");
        errorBuffer.append("Device Model: ").append(Build.MODEL).append("\n");
        errorBuffer.append("Android Version: ").append(Build.VERSION.RELEASE).append("\n");
        errorBuffer.append("App Version: ").append(getAppVersion()).append("\n"); // 需要实现 getAppVersion()
        errorBuffer.append("Error Type: ").append(e.getClass().getName()).append("\n");
        errorBuffer.append("Error Message: ").append(e.getMessage()).append("\n");
        errorBuffer.append("Stack Trace:\n");

        // 获取完整的堆栈跟踪
        StringWriter stackTraceWriter = new StringWriter();
        e.printStackTrace(new PrintWriter(stackTraceWriter));
        errorBuffer.append(stackTraceWriter).append("\n");

        return errorBuffer.toString();
    }

    private String getAppVersion() {
        try {
            return context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionName;
        } catch (Exception e) {
            Log.e(TAG, "Failed to get app version", e);
            return "Unknown";
        }
    }

    private void writeErrorLogToFile(String errorInfo) {
        File logDir = new File(context.getExternalFilesDir(null), LOG_DIR_NAME); // 使用 getExternalFilesDir，不需要额外权限，且应用卸载时自动删除
        // 或者使用内部存储: File logDir = new File(context.getFilesDir(), LOG_DIR_NAME);

        if (!logDir.exists()) {
            logDir.mkdirs(); // 创建目录
        }

        File logFile = new File(logDir, LOG_FILE_NAME);

        try (BufferedWriter writer = new BufferedWriter(
                new FileWriter(logFile, true) // true 表示追加模式
        )) {

            writer.write(errorInfo);
            writer.newLine();
            Log.d(TAG, "Error log written to: " + logFile.getAbsolutePath());

        } catch (IOException ioe) {
            Log.e(TAG, "Failed to write error log to file", ioe);
            // 如果写入文件失败，至少打印到系统日志
            Log.e(TAG, "UNCAUGHT EXCEPTION - Failed to write log: " + errorInfo);
        }
    }

    // （可选）添加上报错误到服务器的逻辑
    private void sendErrorToServer(String errorInfo) {
        // 实现网络请求，将 errorInfo 发送到你的服务器
        // 注意：这里通常需要在后台线程执行，避免阻塞主线程导致应用卡死
        // new Thread(() -> {
        //     try {
        //         // 你的网络请求代码，例如使用 Retrofit, OkHttp, Volley 等
        //         // sendToYourServer(errorInfo);
        //     } catch (Exception ex) {
        //         Log.e(TAG, "Failed to send error to server", ex);
        //     }
        // }).start();
    }
}
